package com.suyang.mongo.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

public class BaseMongoDaoImpl<T> implements BaseMongoDao<T> {
	private static Logger log = Logger.getLogger(BaseMongoDaoImpl.class);

	private Class<T> clz;
	@Autowired
	private MongoTemplate mongoTemplate;

	@SuppressWarnings("unchecked")
	private Class<T> getEntityClass() {
		if (clz == null) {
			clz = ((Class<T>) (((ParameterizedType) (this.getClass().getGenericSuperclass())).getActualTypeArguments()[0]));
		}
		return clz;
	}

	public void save(T t) {
		log.info("[Mongo Dao ]save:" + t);
		this.mongoTemplate.save(t);
	}

	public T queryById(String id) {
		Query query = new Query();
		Criteria criteria = Criteria.where("_id").is(id);
		query.addCriteria(criteria);
		log.info("[Mongo Dao ]queryById:" + query);
		return this.mongoTemplate.findOne(query, this.getEntityClass());
	}

	public List<T> queryList(Query query) {
		log.info("[Mongo Dao ]queryList:" + query);
		return this.mongoTemplate.find(query, this.getEntityClass());
	}

	public T queryOne(Query query) {
		log.info("[Mongo Dao ]queryOne:" + query);
		return this.mongoTemplate.findOne(query, this.getEntityClass());
	}

	public List<T> getPage(Query query, int start, int size) {
		query.skip(start);
		query.limit(size);
		log.info("[Mongo Dao ]queryPage:" + query + "(" + start + "," + size + ")");
		List<T> lists = this.mongoTemplate.find(query, this.getEntityClass());
		return lists;
	}

	/**
	 * 根据条件查询库中符合记录的总数,为分页查询服务
	 * 
	 * @author <a href='mailto:dennisit@163.com'>Cn.苏若年(En.dennisit)</a> Copy
	 *         Right since 2013-10-13 下午03:35:44
	 * 
	 * @param query
	 *            查询条件
	 * @return 满足条件的记录总数
	 */
	public Long getPageCount(Query query) {
		log.info("[Mongo Dao ]queryPageCount:" + query);
		return this.mongoTemplate.count(query, this.getEntityClass());
	}

	public void deleteById(String id) {
		Criteria criteria = Criteria.where("_id").in(id);
		if (null != criteria) {
			Query query = new Query(criteria);
			log.info("[Mongo Dao ]deleteById:" + query);
			if (null != query && this.queryOne(query) != null) {
				this.delete(queryOne(query));
			}
		}
	}

	public void delete(T t) {
		log.info("[Mongo Dao ]delete:" + t);
		this.mongoTemplate.remove(t);
	}

	public void updateFirst(Query query, Update update) {
		log.info("[Mongo Dao ]updateFirst:query(" + query + "),update(" + update + ")");
		this.mongoTemplate.updateFirst(query, update, this.getEntityClass());
	}

	public void updateMulti(Query query, Update update) {
		log.info("[Mongo Dao ]updateMulti:query(" + query + "),update(" + update + ")");
		this.mongoTemplate.updateMulti(query, update, this.getEntityClass());
	}

	public void updateInser(Query query, Update update) {
		log.info("[Mongo Dao ]updateInser:query(" + query + "),update(" + update + ")");
		this.mongoTemplate.upsert(query, update, this.getEntityClass());
	}

}
